#ifndef PHYSICALFIELDFACTORY_H
#define PHYSICALFIELDFACTORY_H

#include <sstream>
#include "PhysicalField.h"
#include "PhysicalField1D.h"
#include "PhysicalField2D.h"
#include "PhysicalField3D.h"

#include "../Input/PicParams.h"
#include "../Parallel/ParallelMPI.h"

#include "../Tool/Macros.h"

class PhysicalFieldFactory {
public:
    static PhysicalField* create(PicParams* params_, ParallelMPI* pmpi_) {
        PhysicalField* fields = NULL;
        if ( params_->geometry == "1d3v" ) {
            fields = new PhysicalField1D(params_, pmpi_);
        }
        else if ( params_->geometry == "2d3v" ) {
            fields = new PhysicalField2D(params_, pmpi_);
        }
        else if ( params_->geometry == "3d3v" ) {
            fields = new PhysicalField3D(params_, pmpi_);
        }
        else {
            log_error<<"Unknwon geometry : " << params_->geometry;
        }

        
        //Fill allfields
        fields->allFields.push_back(fields->Ex_ );
        fields->allFields.push_back(fields->Ey_ );
        fields->allFields.push_back(fields->Ez_ );
        fields->allFields.push_back(fields->Bx_ );
        fields->allFields.push_back(fields->By_ );
        fields->allFields.push_back(fields->Bz_ );
        fields->allFields.push_back(fields->rho_);

        for (int ispec=0; ispec<params_->species_param.size(); ispec++)
        {
            fields->allFields.push_back(fields->rho_s[ispec]);
        }
                    
        fields->allFields_avg.push_back(fields->Ex_avg);
        fields->allFields_avg.push_back(fields->Ey_avg);
        fields->allFields_avg.push_back(fields->Ez_avg);
        fields->allFields_avg.push_back(fields->Bx_avg);
        fields->allFields_avg.push_back(fields->By_avg);
        fields->allFields_avg.push_back(fields->Bz_avg);
        
        /*
        std::stringstream ss;
        for (std::vector<Field*>::iterator iterField=fields->allFields.begin(); iterField!=fields->allFields.end(); iterField++) {
            ss << (*iterField)->name << " ";
        }
        log_info<<"EM fields      : " << ss.str();
        
        ss.str("");
        for (std::vector<Field*>::iterator iterField=fields->allFields_avg.begin(); iterField!=fields->allFields_avg.end(); iterField++) {
            ss << (*iterField)->name << " ";
        }
        log_info<<"EM avg. fields : " << ss.str();
        */
        
        
        return fields;
    }

};

#endif

